package com.tieshan.smartwindow.other.pisutil

import com.tencent.mmkv.MMKV
import com.tieshan.smartwindow.other.*
import com.tieshan.smartwindow.other.pisutil.CRC16Utils.bytesToInt
import timber.log.Timber
import java.nio.charset.Charset
import java.util.*
import kotlin.collections.ArrayList

/**
 * author : Hleo
 * time   : 2022/2/10
 * desc   : pis数据解析
 * 数据格式: 协议头（3个字节）  消息计数值（2个字节）  发送设备IP地址（2个字节） 接收设备IP地址（2个字节）  消息号（1个字节） 功能码（2个字节） 负载数据长度（2个字节） 负载数据（<1024个字节） crc高8校验（1个字节） crc低8校验（1个字节）协议尾固定0B
 */
object UDPDataUtil {
    var strHead = "13850F" //协议头
    var strEnd = "0B"//协议尾
    var bean = UDPData()

    fun dealWithData(bytedata: ByteArray?): UDPData? {

        Timber.e(CRC16Utils.bytesToHexString(bytedata))
        if (bytedata == null || bytedata.size == 0)
            return null
        try {
            bean.header = bytedata.sliceArray(IntRange(0, 2))
            bean.functionCode = bytedata.sliceArray(IntRange(10, 11))
            bean.dataLength = bytedata.sliceArray(IntRange(12, 13))
            val dataLength = CRC16Utils.bytesToHexString(bean.dataLength)!!.toInt(16)
            Timber.e("数据码=${CRC16Utils.bytesToHexString(bean.functionCode)},数据长度=${
                CRC16Utils.bytesToHexString(
                    bean.dataLength
                )
            },长度=$dataLength")
            bean.data = bytedata.sliceArray(IntRange(14, 14 + dataLength - 1))
            bean.tail = bytedata.sliceArray(IntRange(16 + dataLength, 16 + dataLength))

        //判断如果不是正常的协议头和协议尾，则此数据无效
        if (!CRC16Utils.bytesToHexString(bean.header)!!.toUpperCase()
                .equals(strHead) || !CRC16Utils.bytesToHexString(bean.tail)!!.toUpperCase()
                .equals(strEnd)
        )
            return null
        val data = bean.data
        if (bean.data == null || bean.data!!.size == 0)
            return null
        when (CRC16Utils.bytesToHexString(bean.functionCode)) {
            //心跳数据
            functionCode.heartCode -> {
                    val heartdata = UDPData.HeartData()
                    heartdata.jihuoCode = data!![1].toInt()
                    bean.heart = heartdata
            }

            //中文站点信息
            functionCode.cnStationCode -> {
                    val cnStationList: ArrayList<UDPData.CnStationBean> = arrayListOf()//中文站点集合
                    var index = 0
                    while (index < data!!.size) {
                        //站点+站点id的长度
                        val length = data[index].toInt()
                        val station = String(
                            data.sliceArray(IntRange(index + 1, length + index - 1)),
                            Charset.forName("GBK")
                        )
                        val id = data[length + index].toInt()
                        index = length + index + 1
                        val stationBean = UDPData.CnStationBean()
                        stationBean.staionName = station
                        stationBean.id = id
                        //如果是环线数据，则会出现数据重复的情况,则此时重复的id替换为最后一个站点的id+1
                        if (cnStationList.contains(stationBean)) {
                            stationBean.id = cnStationList.get(cnStationList.size - 1).id + 1
                        }
                        cnStationList.add(stationBean)
                    }
                    bean.cnStationList = cnStationList;
            }

            //英文站点信息
            functionCode.enStationCode -> {
                    val enStationList: ArrayList<UDPData.EnStationBean> = arrayListOf()//中文站点集合
                    var index = 0
                    while (index < data!!.size) {
                        //站点+站点id的长度
                        val length = data[index].toInt()
                        val station =
                            String(data.sliceArray(IntRange(index + 1, length + index - 1)))
                        val id = data[length + index].toInt()
                        index = length + index + 1
                        val stationBean = UDPData.EnStationBean()
                        stationBean.staionName = station
                        stationBean.id = id
                        //如果是环线数据，则会出现数据重复的情况,则此时重复的id替换为最后一个站点的id+1
                        if (enStationList.contains(stationBean)) {
                            stationBean.id = enStationList.get(enStationList.size - 1).id + 1
                        }
                        enStationList.add(stationBean)
                    }
                    bean.enStationList = enStationList
            }
            //列车位置状态
            functionCode.trainlocationCode -> {
                    val trainlocation = UDPData.TrainLocationData()
                    trainlocation.status = data!![0].toInt()
                    trainlocation.endLocationId = data[1].toInt()
                    trainlocation.startLocationId = data[2].toInt()
                    trainlocation.nowLocationId = data[3].toInt()
                    trainlocation.nextLocationId = data[4].toInt()

                    bean.location = trainlocation
            }
            //时间速度温度显示
            functionCode.timespeedCode -> {
                    val timespeed = UDPData.TimeSpeedData()
                    timespeed.year =
                        CRC16Utils.bytesToHexString(data!!.sliceArray(IntRange(1, 2)))!!.toInt(16)
                    timespeed.month = data[3].toInt()
                    timespeed.day = data[4].toInt()
                    timespeed.hour = data[5].toInt()
                    timespeed.min = data[6].toInt()
                    timespeed.sec = data[7].toInt()
                    timespeed.speed =
                        CRC16Utils.bytesToHexString(data.sliceArray(IntRange(9, 10)))!!.toInt(16)

                    bean.timeSpeed = timespeed
            }
            //文本信息显示
            // 0006表示向内显终端设备发送文本显示信息
            functionCode.textBackCode, functionCode.textInVisibleCode, functionCode.textThinCode -> {
                try {
                    val text = UDPData.TextData()
                    text.isUrgent = if (data!![0].toInt() == 0) false else true
                    text.isCn = if (data[1].toInt() == 0) true else false
                    //文本输入内容
                    var content = ""
                    if (text.isCn) {
                        content = String(
                            data.sliceArray(IntRange(2, data.size - 1)),
                            Charset.forName("GBK")
                        )
                    } else {
                        content =
                            String(data.sliceArray(IntRange(2, data.size - 1)), Charsets.US_ASCII)
                    }
                    text.content = content
                    bean.textInfo = text
                } catch (e: Exception) {
                    Timber.e("数据解析，文本异常=${e.message}")
                }
            }
            //车次信息
            functionCode.carNumberCode -> {
                    val carnumberdata = UDPData.CarnumberData()
                    carnumberdata.isJiami =
                        if (data!![0].toInt() == 0) false else true
                    carnumberdata.isTest = if (data[1].toInt() == 0) false else true
                    carnumberdata.isTemoNumber = if (data[2].toInt() == 0) false else true
                    carnumberdata.textLong = data[3].toInt()
                    carnumberdata.carNumber = String(
                        data.sliceArray(IntRange(4, 4 - 1 + carnumberdata.textLong)),
                        Charset.forName("GBK")
                    )
                    bean.carnumberInfo = carnumberdata
//              d
            }

        }
        return bean
        } catch (e: Exception) {
            return null
            Timber.e("异常=${e}")
        }
    }

    var timeCorrect = true


    object functionCode {
        //心跳数据功能码
        var heartCode = "0001"

        //中文站点信息
        var cnStationCode = "0002"

        //英文站点信息
        var enStationCode = "0003"

        //列车位置状态
        var trainlocationCode = "0004"

        //时间速度内外温
        var timespeedCode = "0005"

        //文本信息显示-向内显终端设备发送文本显示信息
        var textInVisibleCode = "0006"

        //车次信息显示
        var carNumberCode = "0007"

        //文本信息显示-向背靠背曲面终端设备发送文本显示信息
        var textBackCode = "0206"

        //文本信息显示-向超薄双面终端设备发送文本显示信息
        var textThinCode = "0306"
    }


}